Skip to content

feat(pit): bring the Moshpit namespace into app.moshcode.sh - #113

Merged
ralyodio merged 1 commit into
mainfrom
feat/moshpit-namespace
Jul 31, 2026
Merged

feat(pit): bring the Moshpit namespace into app.moshcode.sh#113
ralyodio merged 1 commit into
mainfrom
feat/moshpit-namespace

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Moves the Moshpit TLD registry out of the moshcoding app and into this PWA, so a TLD is owned by the same account moshcode login establishes instead of a second, unrelated one.

Previously: claiming .eggs used a moshcoding account, the CLI authenticated against a moshcode account, and there was no way to reach the registry from the dashboard you actually sign into.

What's here

file
src/lib/moshpit-name.mjs validation + policy — no db import, so a client can reuse it
src/moshpit.mjs storage: claim, alias, exempt, resolve
src/routes/moshpit.mjs the API + /pit
src/migrations/006_moshpit.sql moshpit_tlds, the append-only log, exemptions
scripts/seed-moshpit-tld.mjs assigns .moshpit to the operator; idempotent

Ownership hangs off users(id). Claims are decided by the PRIMARY KEY, not a read-then-write — the insert is the check, so two simultaneous claims can't both pass. moshpit_tld_log is append-only and is the record of who claimed first; the moshpit_tlds row is a cache of it.

Resolution precedence (tronbrowser.dev)

GET /api/moshpit/resolve?name=<name>&mode=<clearnet|moshpit> now returns prefer:

prefer client should
clearnet ignore the pit — nothing registered
fallback use the pit only when DNS doesn't answer
moshpit use the pit even when DNS answers

mode=clearnet is the default and yields fallback for a registered name — DNS stays authoritative, the pit fills gaps. mode=moshpit is the opt-in that lets profullstack.ai in the pit outrank a squatted profullstack.ai in clearnet.

Two deliberate calls:

  • The server doesn't check whether clearnet answers. The extension is the thing holding the DNS result, and an ICANN TLD list baked in here would be stale within the week. The server states the rule; the client applies it.
  • Overriding DNS is never the default. A resolver that silently outranked real DNS the first time it was switched on would hijack names its operator never meant to touch. There's a test asserting no falsy/unknown mode can ever produce moshpit.

Verification

  • npm test146 pass, 0 fail (26 new)
  • Migration 006 applies cleanly on a fresh database
  • Booted the real server: /pit 200, /api/moshpit/tlds 200, /api/moshpit/resolve 200, malformed name 400

Follow-ups (not in this PR)

  • Repoint pit.moshcode.sh from the moshcoding service to this one
  • Seed .moshpit here
  • Retire the moshpit routes in moshcoding once this is live

🤖 Generated with Claude Code

The TLD registry lived in the moshcoding app, which meant claiming
.eggs used a moshcoding account while the CLI authenticated against a
moshcode one. Two identities for one network, and no way to reach the
registry from the dashboard you actually sign into.

Ported here so a TLD is owned by a `users` row -- the same account
`moshcode login` establishes.

  src/lib/moshpit-name.mjs  validation + policy, no db import
  src/moshpit.mjs           storage: claim, alias, exempt, resolve
  src/routes/moshpit.mjs    the API and /pit
  src/migrations/006        moshpit_tlds, the append-only log, exemptions
  scripts/seed-moshpit-tld  assigns .moshpit to the operator, idempotent

Also adds the resolution-precedence option tronbrowser.dev needs:
GET /api/moshpit/resolve?name=&mode= returns `prefer`, one of clearnet /
fallback / moshpit. Default mode is clearnet, where a registered name
only fills a gap DNS leaves ("fallback"); mode=moshpit is the opt-in
that lets a name in the pit outrank a squatted clearnet domain.

Whether clearnet actually answers is deliberately not decided here. The
extension is the thing holding the DNS result, and an ICANN TLD list
baked into the server would be stale within the week -- so the server
states the rule and the client applies it. Overriding DNS is never the
default: a resolver that silently outranked real DNS the first time it
was switched on would hijack names its operator never meant to touch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

@ralyodio
ralyodio merged commit a3261f6 into main Jul 31, 2026
3 checks passed
@ralyodio
ralyodio deleted the feat/moshpit-namespace branch July 31, 2026 02:53
ralyodio added a commit that referenced this pull request Jul 31, 2026
Resolved against the work that landed since this branch was cut:

- sessions.mjs: keep main's buffered watcher (subscribe before replaying the
  scrollback), its credit balance in the app bar, and its command-ack
  validation. The size frame goes out before the replay — the emulator has to
  be the right width before the first replayed line reaches it — and a resize
  arriving mid-replay is held and flushed behind it like any other event.
- mirror.mjs: keep main's engineDirty flush condition; geometry rides along
  with the same post.
- Dropped the /pit route this branch added: main now serves /pit as the
  Moshpit namespace page (#113), and sessionsRouter is mounted first, so
  keeping it would have shadowed that page.
- Renumbered the migration to 007, behind main's 006_moshpit.sql.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant